package cc.rengu.redp.bizimpl.utils;

import cc.rengu.redp.bizimpl.enums.ValidatMethodEnum;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Daniel on 2020/4/16.
 */
public class StringValicationUtil {

    /**
     * 身份证号校验
     *
     * @param identityNum
     * @return
     */
    private static boolean checkIdentityNum(String identityNum) {
        // regEx =
        // "^(\\d{6})(18|19|20)?(\\d{2})([01]\\d)([0123]\\d)(\\d{3})(\\d|X|x)?$";
        String isIDCard15 = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$";
        String isIDCard18 = "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{4}$";
        Pattern pattern15 = Pattern.compile(isIDCard15);
        Pattern pattern18 = Pattern.compile(isIDCard18);
        Matcher matcher15 = pattern15.matcher(identityNum);
        Matcher matcher18 = pattern18.matcher(identityNum);
        String sub = identityNum.substring(0, identityNum.length() - 1);
        String lastNum = identityNum.substring(identityNum.length() - 1);
        int[] weight = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }; // 十七位数字本体码权重
        char[] validate = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2' }; // mod11,对应校验码字符值
        int sum = 0;
        int mode = 0;
        for (int i = 0; i < sub.length(); i++) {
            sum = sum + Integer.parseInt(String.valueOf(sub.charAt(i))) * weight[i];
        }
        mode = sum % 11;
        String number = String.valueOf(validate[mode]);
        return (matcher15.matches() || (matcher18.matches() && lastNum.equals(number)));
    }

    /**
     *
     * 校验 手机号和座机验证
     *
     * @param phone
     * @return
     */
    private static boolean checkPhone(String phone) {
        String regEx = "^1[3-9]{1}[0-9]{9}$";
        String tregEx = "[0]{1}[0-9]{2,3}-[0-9]{7,8}"; // 表示a或f 0832-80691990
        return Pattern.compile(regEx).matcher(phone).matches() || Pattern.compile(tregEx).matcher(phone).find();
    }

    /**
     * 判断座机电话
     *
     * @param input
     * @return
     */
    private static boolean isPhoneNumber(String input) {
        String reg = "(?:(\\(\\+?86\\))(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)|"
                + "(?:(86-?)?(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)";
        return Pattern.matches(reg, input);
    }

    /**
     * 邮箱判断
     */
    private static boolean checkEmail(String email) {
		String str = "^([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)*@([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)+[\\.][A-Za-z]{2,3}([\\.][A-Za-z]{2})?$";
		Pattern p = Pattern.compile(str);
        return p.matcher(email).matches();
    }

    /**
     * 日期时间格式判断（格式如2011-08-15 13:40:00）
     * @param date
     * @return
     */
    private static boolean checkTimestamp(String date){
        Pattern p = Pattern.compile("^(?:[0-9]{4})-(?:(?:0[1-9])|(?:1[0-2]))-(?:(?:[0-2][1-9])|(?:[1-3][0-1])) (?:(?:[0-2][0-3])|(?:[0-1][0-9])):[0-5][0-9]:[0-5][0-9]$");
        return p.matcher(date).matches();
    }

    /**
     * 匹配8位日期,如20110815
     * @param date
     * @return
     */
    private static boolean checkDate8(String date){
        Pattern p = Pattern.compile("^(?:(?:(?:(?=\\d{2}(?:(?:[02468][048])|(?:[13579][26])))\\d{4}02(?!00)[0-2]\\d))|(?:\\d{4}(?:(?:(?:(?:0[469])|(?:11))(?!00)(?:(?:[0-2]\\d)|(?:30)))|(?:(?:(?:0[13578])|(?:1[02]))(?!00)(?:(?:[0-2]\\d)|(?:3[01])))|(?:02(?!(?:00)|(?:29))[0-2]\\d))))$");
        return p.matcher(date).matches();
    }
    /**
     * 匹配10位日期,如2011-08-15
     * @param date
     * @return
     */
    private static boolean checkDate10(String date){
        Pattern p = Pattern.compile("^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))$");
        return p.matcher(date).matches();
    }

    /**
     * 匹配8位时间,如10:21:30
     * @param date
     * @return
     */
    private static boolean checkTime8(String date){
        Pattern p = Pattern.compile("^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9]):([0-5]?[0-9])?$");
        return p.matcher(date).matches();
    }
    /**
     * 匹配6位时间,如102130
     * @param date
     * @return
     */
    private static boolean checkTime6(String date){
        Pattern p = Pattern.compile("^(([0-1]?[0-9])|([2][0-3]))([0-5]?[0-9])([0-5]?[0-9])?$");
        return p.matcher(date).matches();
    }

    /**
     * 判断银行卡
     *
     * @param cardNo
     * @return
     */
    private static boolean checkBankCardNo(String cardNo) {
        return Pattern.compile("^([1-9]{1})(\\d{14}|\\d{15}|\\d{16}|\\d{17}|\\d{18})$").matcher(cardNo).matches();
    }

    /**
     * 验证只有数字
     */
    private static boolean checkNum(String num) {
        Pattern p = Pattern.compile("^[0-9]*$");
        return p.matcher(num).matches();
    }

    /**
     * 请输入有效的数字，可含1-3位小数
     * @param num
     * @return
     */
    private static boolean check1to3Dec(String num){
        Pattern p = Pattern.compile("^[0-9]+(.[0-9]{1,3})?$");
        return p.matcher(num).matches();
    }

    /**
     * 请输入有效的数字，可含1-2位小数
     * @param num
     * @return
     */
    private static boolean check1to2Dec(String num){
        Pattern p = Pattern.compile("^[0-9]+(.[0-9]{1,2})?$");
        return p.matcher(num).matches();
    }

    /**
     * 邮编校验
     * @param num
     * @return
     */
    private static boolean checkZipcode(String num){
        Pattern p = Pattern.compile("^[0-9]{6}$");
        return p.matcher(num).matches();
    }

    /**
     * 经纬度校验
     * @param num
     * @return
     */
    private static boolean checkLongitudeOrLatitude(String num) {
        Pattern p = Pattern.compile("^(\\-)?\\d{1,3}(\\.\\d{1,8})?$");
        return p.matcher(num).matches();
    }
    /**
     * 字母数字校验
     * @param num
     * @return
     */
    private static boolean checkAlphOrNum(String num) {
        Pattern p = Pattern.compile("^[A-Za-z0-9]+$");
        return p.matcher(num).matches();
    }

    /**
     * ip地址校验 支持IPV4、IPV6
     * @param value
     * @return
     */
    private static boolean checkIP(String value){
        String patternIpv4 = "^((22[0-3]|2[0-1][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})([.](25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|0[1 -9][0-9]|([0-9])]{1,2})){3})$";
        String patternIpv6 = "^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$";
        Pattern pIpv4 = Pattern.compile(patternIpv4);
        Pattern pIpv6 = Pattern.compile(patternIpv6);
        return pIpv4.matcher(value).matches()||pIpv6.matcher(value).matches();
    }
    /**
     * 域名校验
     * @param value
     * @return
     */
    private static boolean checkDomain(String value){
        String domainRegex = "^((http://)|(https://))?([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(/)";
        Pattern p = Pattern.compile(domainRegex);
        return p.matcher(value).matches();
    }



    public static String validate(ValidatMethodEnum validatMethodEnum, String value){
        switch (validatMethodEnum){
            case CHECK_ISNUM:
                if(!checkNum(value)){
                    return ValidatMethodEnum.CHECK_ISNUM.getDesc();
                }
                break;
            case CHECK_PHONE:
                if(!checkPhone(value)){
                    return ValidatMethodEnum.CHECK_PHONE.getDesc();
                }
                break;
            case CHECK_1TO2_DEC:
                if(!check1to2Dec(value)){
                    return ValidatMethodEnum.CHECK_1TO2_DEC.getDesc();
                }
                break;
            case CHECK_1TO3_DEC:
                if(!check1to2Dec(value)){
                    return ValidatMethodEnum.CHECK_1TO3_DEC.getDesc();
                }
                break;
            case CHECK_TIMESTAMP:
                if(!check1to2Dec(value)){
                    return ValidatMethodEnum.CHECK_TIMESTAMP.getDesc();
                }
                break;
            case CHECK_BANK_CARD_NO:
                if(!check1to2Dec(value)){
                    return ValidatMethodEnum.CHECK_BANK_CARD_NO.getDesc();
                }
                break;
            case CHECK_IDENTITY_NUM:
                if(!checkIdentityNum(value)){
                    return ValidatMethodEnum.CHECK_IDENTITY_NUM.getDesc();
                }
                break;
            case CHECK_EMAIL:
                if(!checkEmail(value)){
                    return ValidatMethodEnum.CHECK_EMAIL.getDesc();
                }
                break;
            case CHECK_LONGITUDE_OR_LATITUDE:
                if(!checkLongitudeOrLatitude(value)){
                    return ValidatMethodEnum.CHECK_LONGITUDE_OR_LATITUDE.getDesc();
                }
                break;
            case CHECK_ALPH_OR_NUM:
                if(!checkAlphOrNum(value)){
                    return ValidatMethodEnum.CHECK_ALPH_OR_NUM.getDesc();
                }
                break;
            case CHECK_IP:
                if(!checkIP(value)){
                    return ValidatMethodEnum.CHECK_IP.getDesc();
                }
                break;
            case CHECK_DOMAIN:
                if(!checkDomain(value)){
                    return ValidatMethodEnum.CHECK_DOMAIN.getDesc();
                }
                break;
            case CHECK_DATE8:
                if(!checkDate8(value)){
                    return ValidatMethodEnum.CHECK_DATE8.getDesc();
                }
                break;
            case CHECK_DATE10:
                if(!checkDate10(value)){
                    return ValidatMethodEnum.CHECK_DATE10.getDesc();
                }
                break;
            case CHECK_TIME6:
                if(!checkTime6(value)){
                    return ValidatMethodEnum.CHECK_TIME6.getDesc();
                }
                break;
            case CHECK_TIME8:
                if(!checkTime8(value)){
                    return ValidatMethodEnum.CHECK_TIME8.getDesc();
                }
                break;

        }
        return "";
    }
}
